import { Component, OnDestroy, OnInit, ViewChild, EventEmitter } from '@angular/core';
import { MatPaginator } from '@angular/material';
import { merge, of as observableOf } from 'rxjs';
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { Router } from '@angular/router';
import { MatDialog } from '@angular/material';
import { RestService } from '../services/rest.service';
import { TranslateService } from '@ngx-translate/core';
import { UserDialogComponent } from './user-dialog/user-dialog.component';
import { PasswordDialogComponent } from './password-dialog/password-dialog.component';
import { DialogTypes, ActionTypes } from '../models/wdl-types';

import * as _ from 'lodash';

@Component({
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.css'],
})
export class UserComponent implements OnInit, OnDestroy {
  url = 'api/keycloak/user';
  institution: any;
  user: any;
  displayedColumns: string[] = ['number', 'username', 'lastName', 'role', 'actions'];
  dataSource = [];
  searchText = '';
  cares = [];

  resultsLength = 0;
  pageSize = 200;
  isLoadingResults = true;

  search: EventEmitter<any> = new EventEmitter();

  @ViewChild(MatPaginator) paginator: MatPaginator;

  constructor(public dialog: MatDialog,
              private router: Router,
              private translate: TranslateService,
              private rest: RestService) {
    this.institution = this.rest.getInstitution();
    if (!this.institution.id) {
      console.error('Instituion is invalid: ' + this.institution.id);
    }
    this.user = this.rest.getUser();
    if (!this.isUserQualified()) {
      this.displayedColumns = ['username', 'lastName', 'role'];
    }
  }

  isUserQualified() {
    return this.user.role === 'admin';
  }

  refreshSearch() {
    this.paginator.pageIndex = 0;
    this.search.emit(this.searchText);
  }

  add() {
    this.dialog.open(UserDialogComponent, {
      disableClose: false,
      autoFocus: false,
      width: '450px',
      data: {
        mode: ActionTypes.ADD,
        cares: this.cares,
        institution: this.institution
      }
    }).afterClosed().subscribe(data => {
      if (!data || _.isString(data)) {
        // action was aborted
        return;
      }

      this.rest.post(this.url, data).subscribe((resp) => {
        this.refreshSearch();
      }, message => {
        this.rest.showHttpError('addUserError', message);
      });
    });
  }

  modify(item) {
    const index = _.findIndex(this.dataSource, {username: item.username});
    this.dialog.open(UserDialogComponent, {
      disableClose: false,
      autoFocus: false,
      width: '450px',
      data: {
        mode: ActionTypes.MODIFY,
        item: index !== -1 ? this.dataSource[index] : item,
        cares: this.cares,
        institution: this.institution
      }
    }).afterClosed().subscribe(data => {
      if (!data || _.isString(data)) {
        // action was aborted
        return;
      }

      this.rest.put(this.url + '/' + item.id, data).subscribe(response => {
        this.refreshSearch();
      }, message => {
        this.rest.showHttpError('modifyUserError', message);
      });
    });
  }

  remove(user) {
    const title = this.translate.get('deleteConfirmation')['value'];
    const message = this.translate.get('deleteUserMessage', {username: user.username})['value'];

    this.rest.openGenDialog(DialogTypes.CONFIRMATION, title, message, () => {
      this.rest.delete(this.url + '/' + user.id).subscribe(result => {
        this.refreshSearch();
      }, error => {
        this.rest.showHttpError(this.translate.get('error')['value'], error);
      });
    });
  }

  changePassword(user) {
    this.dialog.open(PasswordDialogComponent, {
      disableClose: false,
      autoFocus: false,
      width: '450px',
      data: {
        item: user
      }
    }).afterClosed().subscribe(data => {
      if (!data || _.isString(data)) {
        // action was aborted
        return;
      }

      this.rest.put(this.url + '/' + user.id + '/reset-password', data).subscribe(response => {
        this.refreshSearch();
      }, message => {
        this.rest.showHttpError('resetPasswordError', message);
      });
    });
  }

  getAllPersonIn() {
    this.rest.getWithParams('/data/person/search/monitorAllIn', {
      institutionId: this.institution.id,
      checkoutTime: 1
    }).subscribe(resp => {
      this.cares = resp['_embedded']['persons'];
    }, () => {
      /*
      this.cares = [
        {id: 1, personName: 'test1', rid: '1234'},
        {id: 2, personName: 'test2', rid: '3456'},
        {id: 3, personName: 'test3', rid: '5678'}
      ];
      this.dataSource = [
        {number: 1, username: 'test1', role: 'admin', cares: []},
        {number: 2, username: 'test2', role: 'header', cares: []},
        {number: 3, username: 'test3', role: 'family', cares: ['1', '2']}
      ];
      */
      console.error('Failed to get all persons in.');
    });
  }

  ngOnInit() {
    merge(this.paginator.page, this.search)
    .pipe(
      startWith({}),
      switchMap(() => {
        this.isLoadingResults = true;

        const params = {
          institution: this.institution.instName,
          first: this.paginator.pageIndex ? this.paginator.pageIndex : 0,
          max: this.paginator.pageSize ? this.paginator.pageSize : this.pageSize
        };

        if (this.searchText) {
          params['search'] = this.searchText;
        }

        return this.rest.getWithParams(this.url + 's', params);
      }),
      map(data => {
        this.isLoadingResults = false;
        this.resultsLength = data['page']['total'];

        let number = this.paginator.pageIndex * this.paginator.pageSize;
        const items = data['users'];
        items.forEach(item => {
          item['number'] = ++number;
        });

        return items;
      }),
      catchError(() => {
        this.isLoadingResults = false;
        return observableOf([]);
      })
    ).subscribe(data => this.dataSource = data);

    this.getAllPersonIn();
  }

  ngOnDestroy() {
  }
}
